package com.astar.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils;
import com.astar.config.WxMaConfiguration;
import com.astar.config.WxMaProperties;
import com.astar.domain.UnifiedUserInfo;
import com.astar.dto.WechatInfo;
import com.astar.exception.SessionTokenNullException;
import com.astar.redis.RedisCacheManager;
import com.astar.service.UserInfoService;
import com.astar.util.JsonUtils;
import com.astar.util.ServletUtils;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

/**
 *
 * 小程序相关api接口
 * Created by liuruiyan on 2019/8/25.
 */
@RestController
@RequestMapping("/api/smallApp")
@Slf4j
public class SmallAppController extends BaseController{

    @Autowired
    private WxMaProperties wxMaProperties;

    @Autowired
    private UserInfoService userInfoService;


    /**
     * 小程序登录接口
     * @param code 前端通过wx.login获取的随机码 code
     * @param invalidToken 后台返回的，登录态已经失效的token
     * @return
     */
    @RequestMapping("/login")
    public Object login(String code,String invalidToken){

        if (StringUtils.isBlank(code)) {
            return error(1,"code不能为空");
        }

        final WxMaService wxService = WxMaConfiguration.getMaService(wxMaProperties.getAppid());

        try {

            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(code);
            log.info(session.getSessionKey());
            log.info(session.getOpenid());

            //生成token，将基本信息存入redis中 ，
            // 1.生成token
            // 2.根据unionid，查询数据库用户信息
            // 3.把token当做key，将用户信息存入redis中
            // 4.返回token信息给前端
            String token  = UUID.randomUUID().toString();
            UnifiedUserInfo unifiedUserInfo = userInfoService.queryInfoByUnionId(session.getUnionid());
            WechatInfo wechatInfo = WechatInfo.builder().wxMaJscode2SessionResult(session).unifiedUserInfo(unifiedUserInfo).build();

            //不设置session有效期（待考虑），等前端判断登录态失效后，将token传过来，删除redis缓存
            setUserInfoToRedis(token,wechatInfo);
            if(StringUtils.isNotBlank(invalidToken)){
                delUserInfoFromRedis(invalidToken);
            }
            return successData(token);

        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
            return error(10,"系统异常");
        }
    }


    /**
     * <pre>
     * 小程序获取用户信息接口 ，
     *
     * TODO 1.是否需要一个拦截器，判断请求头里有没有token，如果没有token，则返回相应状态码
     * TODO 2.是否需要token获取redis里的用户信息，如果信息不存在，则返回状态码告知前台，用户登录态已过期，需要执行登录方法（前提：后台设置了redis缓存有效期）
     * </pre>
     */
    @GetMapping("/userInfo")
    public Object userInfo(String signature, String rawData, String encryptedData, String iv) {

        final WxMaService wxService = WxMaConfiguration.getMaService(wxMaProperties.getAppid());

        WechatInfo wechatInfo = null;
        try {
            wechatInfo = getUserInfoFromRedis();
        } catch (SessionTokenNullException e) {
            e.printStackTrace();
            log.error("请求头token为空");
            return error(3,"请求头token为空");
        }

        String sessionKey = wechatInfo.getWxMaJscode2SessionResult().getSessionKey();
        System.out.println("获取用户信息，sessionKey:"+sessionKey);
        // 用户信息校验
        if (!wxService.getUserService().checkUserInfo(sessionKey, rawData, signature)) {
            return error(2,"用户信息校验失败");
        }


        log.info("解密后的json串:{}",WxMaCryptUtils.decrypt(sessionKey, encryptedData, iv));
        // 解密用户信息
        WxMaUserInfo userInfo = wxService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
        log.info("解密后的用户信息：{}",userInfo.toString());
        //根据用户的unionid从数据库查询用户基本信息，将基本信息存入redis中 ，
        UnifiedUserInfo unifiedUserInfo = new UnifiedUserInfo();
        copyUserInfo(userInfo,unifiedUserInfo);
        UnifiedUserInfo resultUserInfo = userInfoService.queryInfoAndSave(unifiedUserInfo);
        wechatInfo.setUnifiedUserInfo(resultUserInfo);

        try {
            setUserInfoToRedis(wechatInfo);
        } catch (SessionTokenNullException e) {
            e.printStackTrace();
            log.error("请求头token为空");
            return error(3,"请求头token为空");
        }


        return successData(userInfo);
    }


}
